#!/bin/bash

# 小智ESP32服务器端依赖安装脚本
# 适用于Ubuntu/Debian系统

set -e

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 检查是否为root用户
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "请使用sudo运行此脚本"
        exit 1
    fi
}

# 检查操作系统
check_os() {
    if ! grep -qi ubuntu /etc/os-release && ! grep -qi debian /etc/os-release; then
        log_warning "此脚本主要针对Ubuntu/Debian系统，其他系统可能无法正常工作"
    fi
}

# 更新系统包
update_system() {
    log_info "正在更新系统包列表..."
    apt-get update -y
    log_success "系统包列表更新完成"
}

# 检查系统包是否已安装
check_package() {
    dpkg -l | grep -q "^ii  $1 "
}

# 安装系统依赖
install_system_deps() {
    log_info "正在检查系统依赖..."
    
    local packages_to_install=()
    
    # 基础工具
    local base_tools=(
        "wget" "curl" "git" "build-essential" "software-properties-common"
        "apt-transport-https" "ca-certificates" "gnupg" "lsb-release"
    )
    
    # Python相关
    local python_tools=(
        "python3" "python3-pip" "python3-dev" "python3-venv"
        "python3-setuptools" "python3-wheel"
    )
    
    # 音频处理相关
    local audio_tools=(
        "ffmpeg" "libopus-dev" "portaudio19-dev" "libasound2-dev"
        "pulseaudio" "pulseaudio-utils"
    )
    
    # 其他依赖
    local other_tools=(
        "libssl-dev" "libffi-dev" "zlib1g-dev" "libbz2-dev"
        "libreadline-dev" "libsqlite3-dev" "libncurses5-dev"
        "libncursesw5-dev" "xz-utils" "tk-dev" "libxml2-dev" "libxmlsec1-dev"
    )
    
    # 检查基础工具
    for tool in "${base_tools[@]}"; do
        if ! check_package "$tool"; then
            packages_to_install+=("$tool")
        fi
    done
    
    # 检查Python相关
    for tool in "${python_tools[@]}"; do
        if ! check_package "$tool"; then
            packages_to_install+=("$tool")
        fi
    done
    
    # 检查音频处理相关
    for tool in "${audio_tools[@]}"; do
        if ! check_package "$tool"; then
            packages_to_install+=("$tool")
        fi
    done
    
    # 检查其他依赖
    for tool in "${other_tools[@]}"; do
        if ! check_package "$tool"; then
            packages_to_install+=("$tool")
        fi
    done
    
    if [ ${#packages_to_install[@]} -eq 0 ]; then
        log_success "所有系统依赖已安装"
        return 0
    fi
    
    log_info "需要安装以下系统包: ${packages_to_install[*]}"
    log_info "正在安装缺失的系统依赖..."
    
    apt-get install -y "${packages_to_install[@]}" || {
        log_error "安装系统依赖失败"
        exit 1
    }
    
    log_success "系统依赖安装完成"
}

# 安装Conda
install_conda() {
    log_info "正在检查Conda..."
    
    # 检查conda命令是否可用
    if command -v conda &> /dev/null; then
        log_success "Conda已安装且可用"
        return 0
    fi
    
    # 检查Miniconda是否已安装在默认位置
    if [[ -d "/opt/miniconda3" ]]; then
        log_info "检测到已存在的Miniconda安装，正在配置PATH..."
        
        # 添加conda到PATH
        if ! grep -q "/opt/miniconda3/bin" /etc/profile; then
            echo 'export PATH="/opt/miniconda3/bin:$PATH"' >> /etc/profile
        fi
        export PATH="/opt/miniconda3/bin:$PATH"
        
        # 验证conda是否现在可用
        if command -v conda &> /dev/null; then
            log_success "Conda配置完成"
            return 0
        else
            log_warning "Conda安装存在但无法使用，将尝试重新安装"
            rm -rf /opt/miniconda3
        fi
    fi
    
    log_info "正在安装Miniconda..."
    
    # 下载Miniconda安装脚本
    CONDA_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh"
    CONDA_INSTALLER="/tmp/miniconda_installer.sh"
    
    wget -O "$CONDA_INSTALLER" "$CONDA_URL" || {
        log_error "下载Miniconda失败"
        exit 1
    }
    
    # 安装Miniconda
    bash "$CONDA_INSTALLER" -b -p /opt/miniconda3 || {
        log_error "安装Miniconda失败"
        exit 1
    }
    
    # 清理安装文件
    rm -f "$CONDA_INSTALLER"
    
    # 添加conda到PATH
    if ! grep -q "/opt/miniconda3/bin" /etc/profile; then
        echo 'export PATH="/opt/miniconda3/bin:$PATH"' >> /etc/profile
    fi
    export PATH="/opt/miniconda3/bin:$PATH"
    
    log_success "Miniconda安装完成"
}

# 检查Python版本
check_python_version() {
    local python_cmd=$1
    local min_version=$2
    
    if command -v "$python_cmd" &> /dev/null; then
        local current_version=$($python_cmd --version 2>&1 | cut -d' ' -f2)
        if [[ "$(printf '%s\n' "$min_version" "$current_version" | sort -V | head -n1)" == "$min_version" ]]; then
            return 0
        fi
    fi
    return 1
}

# 检查虚拟环境是否存在
check_venv_exists() {
    if command -v conda &> /dev/null; then
        conda env list | grep -q "xiaozhi-server"
    else
        [[ -d "/opt/xiaozhi-server/venv" ]]
    fi
}

# 创建Python虚拟环境
create_venv() {
    log_info "正在检查Python虚拟环境..."
    
    # 检查Python版本
    if ! check_python_version "python3" "3.8"; then
        log_error "需要Python 3.8或更高版本"
        exit 1
    fi
    
    # 检查虚拟环境是否已存在
    if check_venv_exists; then
        log_success "虚拟环境已存在"
        return 0
    fi
    
    log_info "正在创建Python虚拟环境..."
    
    local venv_path="/opt/xiaozhi-server/venv"
    local project_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    
    # 创建虚拟环境目录
    mkdir -p "$(dirname "$venv_path")"
    
    # 使用conda创建环境
    if command -v conda &> /dev/null; then
        # 初始化conda配置
        source /opt/miniconda3/etc/profile.d/conda.sh
        
        # 检查并接受服务条款
        log_info "正在检查Conda服务条款..."
        if conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main --channel https://repo.anaconda.com/pkgs/r 2>/dev/null || true; then
            log_info "Conda服务条款已接受"
        else
            log_warning "无法自动接受服务条款，尝试继续创建环境"
        fi
        
        # 创建conda环境
        conda create -n xiaozhi-server python=3.10 -y
        log_success "Conda虚拟环境创建完成"
    else
        # 使用venv创建环境
        python3 -m venv "$venv_path"
        log_success "Python虚拟环境创建完成"
    fi
}

# 检查Python包是否已安装
check_python_package() {
    local package=$1
    local version=$2
    
    if command -v conda &> /dev/null; then
        source /opt/miniconda3/etc/profile.d/conda.sh
        conda activate xiaozhi-server
    else
        source /opt/xiaozhi-server/venv/bin/activate
    fi
    
    if [[ -n "$version" ]]; then
        pip list | grep -q "^$package *$version"
    else
        pip list | grep -q "^$package"
    fi
}

# 解析requirements.txt文件
parse_requirements() {
    local req_file=$1
    local packages=()
    
    while IFS= read -r line || [[ -n "$line" ]]; do
        # 跳过空行和注释
        [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
        
        # 提取包名和版本
        if [[ "$line" =~ ^([a-zA-Z0-9_-]+)[[:space:]]*([><=~]+[[:space:]]*[0-9.]+)? ]]; then
            local package="${BASH_REMATCH[1]}"
            local version="${BASH_REMATCH[2]}"
            packages+=("$package:$version")
        fi
    done < "$req_file"
    
    echo "${packages[@]}"
}

# 配置pip镜像源
configure_pip_mirrors() {
    local pip_config_dir="/root/.pip"
    local pip_config_file="$pip_config_dir/pip.conf"
    
    # 检查是否已经配置过清华源
    if [[ -f "$pip_config_file" ]] && grep -q "pypi.tuna.tsinghua.edu.cn" "$pip_config_file"; then
        log_success "pip镜像源已配置（清华源）"
        return 0
    fi
    
    log_info "正在配置pip国内镜像源..."
    
    # 创建pip配置目录
    mkdir -p "$pip_config_dir"
    
    # 创建pip配置文件
    cat > "$pip_config_file" << 'EOF'
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple/
trusted-host = pypi.tuna.tsinghua.edu.cn
timeout = 120
retries = 5

[install]
trusted-host = pypi.tuna.tsinghua.edu.cn
EOF
    
    # 为xiaozhi用户也配置
    if id "xiaozhi" &>/dev/null; then
        local user_pip_dir="/home/xiaozhi/.pip"
        local user_pip_config="$user_pip_dir/pip.conf"
        
        # 检查xiaozhi用户是否已配置
        if [[ ! -f "$user_pip_config" ]] || ! grep -q "pypi.tuna.tsinghua.edu.cn" "$user_pip_config"; then
            mkdir -p "$user_pip_dir"
            cp "$pip_config_file" "$user_pip_config"
            chown -R xiaozhi:xiaozhi "$user_pip_dir"
        fi
    fi
    
    log_success "pip镜像源配置完成"
}

# 安装Python依赖
install_python_deps() {
    log_info "正在检查Python依赖..."
    
    local project_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local requirements_file="$project_path/requirements.txt"
    
    if [[ ! -f "$requirements_file" ]]; then
        log_error "未找到requirements.txt文件: $requirements_file"
        exit 1
    fi
    
    # 配置pip镜像源
    configure_pip_mirrors
    
    # 激活虚拟环境
    if command -v conda &> /dev/null; then
        source /opt/miniconda3/etc/profile.d/conda.sh
        conda activate xiaozhi-server
    else
        source /opt/xiaozhi-server/venv/bin/activate
    fi
    
    # 升级pip（使用镜像源）
    log_info "正在升级pip..."
    pip install --upgrade pip \
        -i https://pypi.tuna.tsinghua.edu.cn/simple/ \
        --trusted-host pypi.tuna.tsinghua.edu.cn \
        --timeout 300 \
        --retries 5
    
    # 解析requirements.txt
    local packages_to_install=()
    local packages_to_upgrade=()
    
    while IFS= read -r line || [[ -n "$line" ]]; do
        # 跳过空行和注释
        [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
        
        # 提取包名和版本要求
        if [[ "$line" =~ ^([a-zA-Z0-9_-]+)[[:space:]]*([><=~]+[[:space:]]*[0-9.]+)? ]]; then
            local package="${BASH_REMATCH[1]}"
            local version_req="${BASH_REMATCH[2]}"
            
            # 检查包是否已安装
            if pip list | grep -q "^$package "; then
                local installed_version=$(pip list | grep "^$package " | awk '{print $2}')
                
                if [[ -n "$version_req" ]]; then
                    # 检查版本是否满足要求（简化检查）
                    log_info "包 $package 已安装 (版本: $installed_version)，版本要求: $version_req"
                    packages_to_upgrade+=("$line")
                else
                    log_info "包 $package 已安装 (版本: $installed_version)"
                fi
            else
                packages_to_install+=("$line")
            fi
        fi
    done < "$requirements_file"
    
    # 安装新包
    if [ ${#packages_to_install[@]} -gt 0 ]; then
        log_info "需要安装以下Python包:"
        printf '%s\n' "${packages_to_install[@]}"
        
        pip install "${packages_to_install[@]}" \
            -i https://pypi.tuna.tsinghua.edu.cn/simple/ \
            --trusted-host pypi.tuna.tsinghua.edu.cn \
            --timeout 300 \
            --retries 5 || {
            log_error "安装Python依赖失败"
            exit 1
        }
    fi
    
    # 升级现有包
    if [ ${#packages_to_upgrade[@]} -gt 0 ]; then
        log_info "需要升级以下Python包:"
        printf '%s\n' "${packages_to_upgrade[@]}"
        
        pip install --upgrade "${packages_to_upgrade[@]}" \
            -i https://pypi.tuna.tsinghua.edu.cn/simple/ \
            --trusted-host pypi.tuna.tsinghua.edu.cn \
            --timeout 300 \
            --retries 5 || {
            log_warning "升级部分Python包失败，可能是版本冲突"
        }
    fi
    
    if [ ${#packages_to_install[@]} -eq 0 ] && [ ${#packages_to_upgrade[@]} -eq 0 ]; then
        log_success "所有Python依赖已满足要求"
    else
        log_success "Python依赖安装完成"
    fi
}

# 创建系统用户
create_user() {
    log_info "正在创建系统用户..."
    
    if id "xiaozhi" &>/dev/null; then
        log_success "用户xiaozhi已存在"
        return 0
    fi
    
    useradd -r -s /bin/bash -d /opt/xiaozhi-server -c "XiaoZhi Server User" xiaozhi
    mkdir -p /opt/xiaozhi-server
    chown xiaozhi:xiaozhi /opt/xiaozhi-server
    
    log_success "系统用户创建完成"
}

# 设置文件权限
set_permissions() {
    log_info "正在设置文件权限..."
    
    local project_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    
    # 设置项目目录权限
    chown -R xiaozhi:xiaozhi "$project_path"
    chmod +x "$project_path/app.py"
    
    # 创建必要的目录
    mkdir -p /tmp/xiaozhi-logs
    chown xiaozhi:xiaozhi /tmp/xiaozhi-logs
    
    log_success "文件权限设置完成"
}

# 检查服务文件是否需要更新
check_service_file() {
    local project_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local service_file="/etc/systemd/system/xiaozhi-server.service"
    
    if [[ ! -f "$service_file" ]]; then
        return 1  # 需要创建
    fi
    
    # 检查服务文件中的路径是否与当前项目路径匹配
    if grep -q "WorkingDirectory=$project_path" "$service_file" && \
       grep -q "ExecStart=$project_path/start_server.sh" "$service_file"; then
        return 0  # 不需要更新
    fi
    
    return 1  # 需要更新
}

# 创建服务文件
create_service() {
    log_info "正在检查系统服务..."
    
    local project_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local service_file="/etc/systemd/system/xiaozhi-server.service"
    
    # 检查服务文件是否已存在且配置正确
    if check_service_file; then
        log_success "系统服务文件已存在且配置正确"
        return 0
    fi
    
    log_info "正在创建/更新系统服务..."
    
    cat > "$service_file" << EOF
[Unit]
Description=XiaoZhi ESP32 Server
After=network.target

[Service]
Type=simple
User=xiaozhi
Group=xiaozhi
WorkingDirectory=$project_path
ExecStart=$project_path/start_server.sh
Restart=always
RestartSec=10
Environment=PATH=/opt/miniconda3/envs/xiaozhi-server/bin:/usr/local/bin:/usr/bin:/bin
StandardOutput=append:/tmp/xiaozhi-logs/server.log
StandardError=append:/tmp/xiaozhi-logs/server-error.log

[Install]
WantedBy=multi-user.target
EOF

    systemctl daemon-reload
    log_success "系统服务创建/更新完成"
}

# 检查启动脚本是否需要更新
check_start_script() {
    local project_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local start_script="$project_path/start_server.sh"
    
    if [[ ! -f "$start_script" ]]; then
        return 1  # 需要创建
    fi
    
    # 检查脚本内容是否正确
    if grep -q "conda activate xiaozhi-server" "$start_script" && \
       grep -q "python app.py" "$start_script"; then
        return 0  # 不需要更新
    fi
    
    return 1  # 需要更新
}

# 创建启动脚本
create_start_script() {
    log_info "正在检查启动脚本..."
    
    local project_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local start_script="$project_path/start_server.sh"
    
    # 检查启动脚本是否已存在且配置正确
    if check_start_script; then
        log_success "启动脚本已存在且配置正确"
        return 0
    fi
    
    log_info "正在创建/更新启动脚本..."
    
    cat > "$start_script" << 'EOF'
#!/bin/bash

# 激活虚拟环境
if command -v conda &> /dev/null; then
    source /opt/miniconda3/etc/profile.d/conda.sh
    conda activate xiaozhi-server
else
    source /opt/xiaozhi-server/venv/bin/activate
fi

# 启动服务器
cd "$(dirname "$0")"
python app.py
EOF

    chmod +x "$start_script"
    log_success "启动脚本创建/更新完成"
}

# 主函数
main() {
    echo "========================================"
    echo "小智ESP32服务器端依赖安装脚本"
    echo "========================================"
    echo ""
    echo "🔍 智能依赖检查和安装"
    echo "- 自动检测已安装的依赖"
    echo "- 仅安装缺失的组件"
    echo "- 跳过已满足的条件"
    echo "========================================"
    
    check_root
    check_os
    
    # 执行安装步骤
    update_system
    install_system_deps
    install_conda
    create_venv
    install_python_deps
    create_user
    set_permissions
    create_start_script
    create_service
    
    echo "========================================"
    log_success "依赖检查和安装完成！"
    echo "========================================"
    echo ""
    echo "📋 后续操作："
    echo "1. 配置config.yaml文件"
    echo "2. 启动服务：sudo systemctl start xiaozhi-server"
    echo "3. 设置开机自启：sudo systemctl enable xiaozhi-server"
    echo "4. 查看状态：sudo systemctl status xiaozhi-server"
    echo "5. 查看日志：sudo journalctl -u xiaozhi-server -f"
    echo ""
    echo "🔧 管理命令："
    echo "- 启动：sudo systemctl start xiaozhi-server"
    echo "- 停止：sudo systemctl stop xiaozhi-server"
    echo "- 重启：sudo systemctl restart xiaozhi-server"
    echo "- 状态：sudo systemctl status xiaozhi-server"
    echo ""
    echo "📁 文件位置："
    echo "- 项目目录：$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    echo "- 日志目录：/tmp/xiaozhi-logs"
    echo "- 服务文件：/etc/systemd/system/xiaozhi-server.service"
    echo "========================================"
}

# 错误处理
trap 'log_error "脚本执行失败，请检查错误信息"; exit 1' ERR

# 运行主函数
main "$@"